package dev.http.httplient4;

/**
 * Author:   RunAtWorld
 * Date:     2021/3/30 1:08
 */

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

/**
 * httpclient 4.5
 */
@Slf4j
public class HttpsClient4Util {

    /**
     * 带请求体发GET请求
     *
     * @param url
     * @param headers
     * @param params
     * @return
     */
    public static String doGet(String url, Map headers, String params) {
        String urlGet = StringUtils.isEmpty(params) ? url : url + params;
        // 创建GET请求
        HttpRequestBase httpGet = new HttpGet(urlGet);
        return send(headers, httpGet);
    }

    private static String send(Map headers, HttpRequestBase httpMethod) {
        // 设置配置请求参数
        RequestConfig requestConfig = RequestConfig.custom()
                // 连接主机服务超时时间
                .setConnectTimeout(35 * 1000)
                // 请求超时时间
                .setConnectionRequestTimeout(35 * 1000)
                // 数据读取超时时间
                .setSocketTimeout(60 * 1000)
                .build();
        httpMethod.setConfig(requestConfig);

        // 设置请求头
        httpMethod.addHeader("Content-Type", "application/json;charset=utf8");
        if (headers != null) {
            headers.forEach((k, v) -> {
                httpMethod.setHeader(k.toString(), v.toString());
            });
        }

        // 由客户端执行(发送)请求
        try (CloseableHttpClient client = getHttpsClient();
             CloseableHttpResponse response = client.execute(httpMethod)) {
            HttpEntity responseEntity = response.getEntity();
            log.info("响应状态为:" + response.getStatusLine());
            log.info("响应信息:{}", response.toString());
            if (responseEntity != null) {
                log.info("响应实体:{}", responseEntity.toString());
                log.info("响应内容长度为:" + responseEntity.getContentLength());
                String resp = EntityUtils.toString(responseEntity);
                log.info("响应内容为:{}", resp);
                return resp;
            }
        } catch (ClientProtocolException e) {
            log.error("ClientProtocolException:{}", e.getMessage());
            e.printStackTrace();
        } catch (ParseException e) {
            log.error("ParseException:{}", e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            log.error("IOException:{}", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 带请求体发POST请求
     *
     * @param url
     * @param headers
     * @param body
     * @return
     */
    public static String doPost(String url, Map headers, Object body) {
        // 创建POST请求
        HttpPost httpPost = new HttpPost(url);

        // 构建POST请求体
        StringEntity entity = new StringEntity(JSON.toJSONString(body), "UTF-8");
        // 设置post请求体
        httpPost.setEntity(entity);
        // 设置请求头
        httpPost.addHeader("Content-Type", "application/json;charset=utf8");
        headers.forEach((k, v) -> {
            httpPost.setHeader(k.toString(), v.toString());
        });
        return send(headers, httpPost);
    }

    /**
     * 获取 HttpsClient
     * @return
     */
    private static CloseableHttpClient getHttpsClient() {
        SSLContext sslContext = null;
        try {
            sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustAllStrategy()).build();
        } catch (NoSuchAlgorithmException e) {
            log.error("NoSuchAlgorithmException:{}", e.getMessage());
            e.printStackTrace();
        } catch (KeyManagementException e) {
            log.error("KeyManagementException:{}", e.getMessage());
            e.printStackTrace();
        } catch (KeyStoreException e) {
            log.error("KeyStoreException:{}", e.getMessage());
            e.printStackTrace();
        }

        SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext);
        return HttpClients.custom().setSSLSocketFactory(factory).build();
    }
}